﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using Microsoft.IdentityModel;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Security;
using System.IdentityModel.Tokens;
using Microsoft.IdentityModel.Protocols.WSTrust;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Claims;
using System.Xml;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Administration;
using Microsoft.SharePoint.Utilities; 
using System.ComponentModel;
using System.IO;
using System.Reflection;
using System.Web.UI.HtmlControls;
using System.Diagnostics;
using System.Runtime;
using System.Xml.Serialization;


namespace AzureConnect
{
    //inheriting from WebControl so that we can get access to the HtmlWriter for the page
    //so we can output data, links, etc.

    //[ToolboxItem(typeof(AzureConnect.WcfConfig))]
    public class WcfConfig : System.Web.UI.WebControls.WebControl
    {
        //the default value for ResponseDivId
        public static string RESPONSE_DIV_ID = "AZUREWCF_azureRequestResultsDiv";

		//defaults for servername and error divs
		public static string SERVERNAME_DIV_ID = "AZUREWCF_azureServerNameDiv";
		public static string ERRORMESSAGE_DIV_ID = "AZUREWCF_azureErrorMessageDiv";
		public static string TRACEINFO_DIV_ID = "AZUREWCF_azureTraceInfoDiv";

        //query string parameter names
        public static string QUERYSTRING_METHODNAME = "methodname";
        public static string QUERYSTRING_METHODPARAMS = "methodparams";
        public static string QUERYSTRING_SERVERCACHENAME = "servercachename";
        public static string QUERYSTRING_SERVERCACHETIME = "servercachetime";
        public static string QUERYSTRING_OUTPUTTYPE = "outputtype";
        public static string QUERYSTRING_DECODERESULTS = "encode";
        public static string QUERYSTRING_ACCESSDENIEDMSG = "accessdenied";
        public static string QUERYSTRING_TIMEOUTMSG = "timeout";

        //the divs where we will output the response from the WCF call
        HtmlGenericControl div = null;
		HtmlGenericControl serverNameDiv = null;
		HtmlGenericControl errorMsgDiv = null;
		HtmlGenericControl traceInfoDiv = null;

        //for WCF configuration
        private const string trustNS = "http://docs.oasis-open.org/ws-sx/ws-trust/200512";

        //these are the WCF configuration objects - they are protected so they can be
        //overridden if needed for some reason in a subsequent subclass 
        protected SecurityBindingElement m_SecurityBinding = 
            SecurityBindingElement.CreateSspiNegotiationOverTransportBindingElement();

        protected BinaryMessageEncodingBindingElement m_BinaryMessage = 
            new BinaryMessageEncodingBindingElement();

        protected HttpsTransportBindingElement m_SecureTransport = 
            new HttpsTransportBindingElement();

        protected WS2007FederationHttpBinding m_FedBinding =
            new WS2007FederationHttpBinding();
		
        protected EndpointAddress m_EndpointAddress = null;

        //property based access to the main binding components
        public SecurityBindingElement SecurityBinding 
        {
            get
            {
                return m_SecurityBinding;
            }
        }

        public BinaryMessageEncodingBindingElement BinaryMessage 
        {
            get
            {
                return m_BinaryMessage;
            }
        }

        public HttpsTransportBindingElement SecureTransport 
        {
            get
            {
                return m_SecureTransport;
            }
        }

        public WS2007FederationHttpBinding FedBinding 
        {
            get
            {
                return m_FedBinding;
            }
        }

        public EndpointAddress WcfEndpointAddress
        {
            get
            {
                return m_EndpointAddress;
            }
            set
            {
                m_EndpointAddress = value;
            }
        }

        //default minimum property value overrides
        protected const int MAX_CONTENT_LENGTH = 65536;

		//default maximum data retrieval timeout
		protected const int MAX_REQUEST_ON_WIRE_TIMEOUT = 30;

		//default minimum cache time in minutes
		protected const int MIN_SERVER_CACHE_TIME = 3;


        //enum for data return methods
        public enum DataOutputType
        {
            Page,
            ServerCache,
            Both,
            None
        }

        //all of the properties that are settable for the binding controls in a
        //control tag in an aspx page.  default values are used so that properties
        //set in the control tag are not overridden by setting the property again
        //in the init event of the control

        #region SecurityBinding LocalClient Settings
        //***************************************************************************
        // SECURITYBINDING LOCALCLIENT SETTINGS
        //***************************************************************************
        //[DefaultValue(SecurityAlgorithmSuite.Basic256Sha256)] - errors 
        public SecurityAlgorithmSuite SecurityBindingDefaultAlgorithmSuite
        {
            get
            {
                return m_SecurityBinding.DefaultAlgorithmSuite;
            }
            set
            {
                m_SecurityBinding.DefaultAlgorithmSuite = value;
            }
        }

        [DefaultValue(SecurityHeaderLayout.Strict)]
        public SecurityHeaderLayout SecurityBindingSecurityHeaderLayout
        {
            get
            {
                return m_SecurityBinding.SecurityHeaderLayout;
            }
            set
            {
                m_SecurityBinding.SecurityHeaderLayout = value;
            }
        }

        [DefaultValue(SecurityKeyEntropyMode.CombinedEntropy)]
        public SecurityKeyEntropyMode SecurityBindingKeyEntropyMode
        {
            get
            {
                return m_SecurityBinding.KeyEntropyMode;
            }
            set
            {
                m_SecurityBinding.KeyEntropyMode = value;
            }
        }

        public bool SecurityBindingIncludeTimestamp
        {
            get
            {
                return m_SecurityBinding.IncludeTimestamp;
            }
            set
            {
                m_SecurityBinding.IncludeTimestamp = value;
            }
        }

        public bool SecurityBindingLocalClientCacheCookies
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.CacheCookies;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.CacheCookies = value;
            }
        }

        public bool SecurityBindingLocalClientDetectReplays
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.DetectReplays;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.DetectReplays = value;
            }
        }

        public int SecurityBindingLocalClientReplayCacheSize
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.ReplayCacheSize;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.ReplayCacheSize = value;
            }
        }

        public int SecurityBindingLocalClientMaxClockSkew
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.MaxClockSkew.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.MaxClockSkew = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalClientMaxCookieCachingTime
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.MaxCookieCachingTime.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.MaxCookieCachingTime = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalClientReplayWindow
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.ReplayWindow.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.ReplayWindow = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalClientSessionKeyRenewalInterval
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.SessionKeyRenewalInterval.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.SessionKeyRenewalInterval = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalClientSessionKeyRolloverInterval
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.SessionKeyRolloverInterval.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.SessionKeyRolloverInterval = TimeSpan.FromMinutes(value);
            }
        }

        public bool SecurityBindingLocalClientReconnectTransportOnFailure
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.ReconnectTransportOnFailure;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.ReconnectTransportOnFailure = value;
            }
        }

        public int SecurityBindingLocalClientTimestampValidityDuration
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.TimestampValidityDuration.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.TimestampValidityDuration = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalClientCookieRenewalThresholdPercentage
        {
            get
            {
                return m_SecurityBinding.LocalClientSettings.CookieRenewalThresholdPercentage;
            }
            set
            {
                m_SecurityBinding.LocalClientSettings.CookieRenewalThresholdPercentage = value;
            }
        }

        //************************************************************************************
        //************************************************************************************
        #endregion

        #region SecurityBinding LocalService Settings
        //***************************************************************************
        // SECURITYBINDING LOCALSERVICE SETTINGS
        //***************************************************************************
        public bool SecurityBindingLocalServiceDetectReplays
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.DetectReplays;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.DetectReplays = value;
            }
        }

        public int SecurityBindingLocalServiceIssuedCookieLifetime
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.IssuedCookieLifetime.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.IssuedCookieLifetime = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalServiceMaxStatefulNegotiations
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.MaxStatefulNegotiations;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.MaxStatefulNegotiations = value;
            }
        }

        public int SecurityBindingLocalServiceReplayCacheSize
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.ReplayCacheSize;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.ReplayCacheSize = value;
            }
        }

        public int SecurityBindingLocalServiceMaxClockSkew
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.MaxClockSkew.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.MaxClockSkew = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalServiceNegotiationTimeout
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.NegotiationTimeout.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.NegotiationTimeout = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalServiceReplayWindow
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.ReplayWindow.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.ReplayWindow = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalServiceInactivityTimeout
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.InactivityTimeout.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.InactivityTimeout = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalServiceSessionKeyRenewalInterval
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.SessionKeyRenewalInterval.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.SessionKeyRenewalInterval = TimeSpan.FromMinutes(value);
            }
        }

        public int SecurityBindingLocalServiceSessionKeyRolloverInterval
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.SessionKeyRolloverInterval.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.SessionKeyRolloverInterval = TimeSpan.FromMinutes(value);
            }
        }

        public bool SecurityBindingLocalServiceReconnectTransportOnFailure
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.ReconnectTransportOnFailure;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.ReconnectTransportOnFailure = value;
            }
        }

        public int SecurityBindingLocalServiceMaxPendingSessions
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.MaxPendingSessions;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.MaxPendingSessions = value;
            }
        }

        public int SecurityBindingLocalServiceMaxCachedCookies
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.MaxCachedCookies;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.MaxCachedCookies = value;
            }
        }

        public int SecurityBindingLocalServiceTimestampValidityDuration
        {
            get
            {
                return m_SecurityBinding.LocalServiceSettings.TimestampValidityDuration.Minutes;
            }
            set
            {
                m_SecurityBinding.LocalServiceSettings.TimestampValidityDuration = TimeSpan.FromMinutes(value);
            }
        }
        //************************************************************************************
        //************************************************************************************
        #endregion

        #region mBinaryMessage Settings
        //***************************************************************************
        // BINARYMESSAGE SETTINGS
        //***************************************************************************
        public int BinaryMessageMaxReadPoolSize
        {
            get
            {
                return m_BinaryMessage.MaxReadPoolSize;
            }
            set
            {
                m_BinaryMessage.MaxReadPoolSize = value;
            }
        }

        public int BinaryMessageMaxWritePoolSize
        {
            get
            {
                return m_BinaryMessage.MaxWritePoolSize;
            }
            set
            {
                m_BinaryMessage.MaxWritePoolSize = value;
            }
        }

        public int BinaryMessageMaxSessionSize
        {
            get
            {
                return m_BinaryMessage.MaxSessionSize;
            }
            set
            {
                m_BinaryMessage.MaxSessionSize = value;
            }
        }

        public int BinaryMessageReaderQuotasMaxDepth
        {
            get
            {
                return m_BinaryMessage.ReaderQuotas.MaxDepth;
            }
            set
            {
                m_BinaryMessage.ReaderQuotas.MaxDepth = value;
            }
        }

        public int BinaryMessageReaderQuotasMaxStringContentLength
        {
            get
            {
                return m_BinaryMessage.ReaderQuotas.MaxStringContentLength;
            }
            set
            {
                m_BinaryMessage.ReaderQuotas.MaxStringContentLength = value;
            }
        }

        public int BinaryMessageReaderQuotasMaxArrayLength
        {
            get
            {
                return m_BinaryMessage.ReaderQuotas.MaxArrayLength;
            }
            set
            {
                m_BinaryMessage.ReaderQuotas.MaxArrayLength = value;
            }
        }

        public int BinaryMessageReaderQuotasMaxBytesPerRead
        {
            get
            {
                return m_BinaryMessage.ReaderQuotas.MaxBytesPerRead;
            }
            set
            {
                m_BinaryMessage.ReaderQuotas.MaxBytesPerRead = value;
            }
        }

        public int BinaryMessageReaderQuotasMaxNameTableCharCount
        {
            get
            {
                return m_BinaryMessage.ReaderQuotas.MaxNameTableCharCount;
            }
            set
            {
                m_BinaryMessage.ReaderQuotas.MaxNameTableCharCount = value;
            }
        }
        //************************************************************************************
        //************************************************************************************
        #endregion

        #region HttpsTransport Settings
        //***************************************************************************
        // HTTPSTRANSPORT SETTINGS
        //***************************************************************************
        [DefaultValue(System.Net.AuthenticationSchemes.Anonymous)]
        public System.Net.AuthenticationSchemes SecureTransportAuthenticationScheme
        {
            get
            {
                return m_SecureTransport.AuthenticationScheme;
            }
            set
            {
                m_SecureTransport.AuthenticationScheme = value;
            }
        }

        [DefaultValue(System.ServiceModel.HostNameComparisonMode.StrongWildcard)]
        public System.ServiceModel.HostNameComparisonMode SecureTransportHostNameComparisonMode
        {
            get
            {
                return m_SecureTransport.HostNameComparisonMode;
            }
            set
            {
                m_SecureTransport.HostNameComparisonMode = value;
            }
        }

        [DefaultValue(System.Net.AuthenticationSchemes.Anonymous)]
        public System.Net.AuthenticationSchemes SecureTransportProxyAuthenticationScheme
        {
            get
            {
                return m_SecureTransport.ProxyAuthenticationScheme;
            }
            set
            {
                m_SecureTransport.ProxyAuthenticationScheme = value;
            }
        }

        [DefaultValue(System.ServiceModel.TransferMode.Buffered)]
        public System.ServiceModel.TransferMode SecureTransportTransferMode
        {
            get
            {
                return m_SecureTransport.TransferMode;
            }
            set
            {
                m_SecureTransport.TransferMode = value;
            }
        }

        public bool SecureTransportManualAddressing
        {
            get
            {
                return m_SecureTransport.ManualAddressing;
            }
            set
            {
                m_SecureTransport.ManualAddressing = value;
            }
        }

        public long SecureTransportMaxBufferPoolSize
        {
            get
            {
                return m_SecureTransport.MaxBufferPoolSize;
            }
            set
            {
                m_SecureTransport.MaxBufferPoolSize = value;
            }
        }

        public long SecureTransportMaxReceivedMessageSize
        {
            get
            {
                return m_SecureTransport.MaxReceivedMessageSize;
            }
            set
            {
                m_SecureTransport.MaxReceivedMessageSize = value;
            }
        }

        public bool SecureTransportAllowCookies
        {
            get
            {
                return m_SecureTransport.AllowCookies;
            }
            set
            {
                m_SecureTransport.AllowCookies = value;
            }
        }

        public bool SecureTransportBypassProxyOnLocal
        {
            get
            {
                return m_SecureTransport.BypassProxyOnLocal;
            }
            set
            {
                m_SecureTransport.BypassProxyOnLocal = value;
            }
        }

        public bool SecureTransportKeepAliveEnabled
        {
            get
            {
                return m_SecureTransport.KeepAliveEnabled;
            }
            set
            {
                m_SecureTransport.KeepAliveEnabled = value;
            }
        }

        public int SecureTransportMaxBufferSize
        {
            get
            {
                return m_SecureTransport.MaxBufferSize;
            }
            set
            {
                m_SecureTransport.MaxBufferSize = value;
            }
        }

        public string SecureTransportRealm
        {
            get
            {
                return m_SecureTransport.Realm;
            }
            set
            {
                m_SecureTransport.Realm = value;
            }
        }

        public bool SecureTransportUnsafeConnectionNtlmAuthentication
        {
            get
            {
                return m_SecureTransport.UnsafeConnectionNtlmAuthentication;
            }
            set
            {
                m_SecureTransport.UnsafeConnectionNtlmAuthentication = value;
            }
        }

        public bool SecureTransportUseDefaultWebProxy
        {
            get
            {
                return m_SecureTransport.UseDefaultWebProxy;
            }
            set
            {
                m_SecureTransport.UseDefaultWebProxy = value;
            }
        }

        public bool SecureTransportRequireClientCertificate
        {
            get
            {
                return m_SecureTransport.RequireClientCertificate;
            }
            set
            {
                m_SecureTransport.RequireClientCertificate = value;
            }
        }
        //************************************************************************************
        //************************************************************************************
        #endregion

        #region FedBinding Settings
        //***************************************************************************
        // FEDBINDING SETTINGS
        //***************************************************************************
        [DefaultValue(HostNameComparisonMode.StrongWildcard)]
        public HostNameComparisonMode FedBindingHostNameComparisonMode
        {
            get
            {
                return m_FedBinding.HostNameComparisonMode;
            }
            set
            {
                m_FedBinding.HostNameComparisonMode = value;
            }
        }

        [DefaultValue(WSMessageEncoding.Text)]
        public WSMessageEncoding FedBindingMessageEncoding
        {
            get
            {
                return m_FedBinding.MessageEncoding;
            }
            set
            {
                m_FedBinding.MessageEncoding = value;
            }
        }

        //[DefaultValue(Encoding.UTF8)] - errors
        public Encoding FedBindingTextEncoding
        {
            get
            {
                return m_FedBinding.TextEncoding;
            }
            set
            {
                m_FedBinding.TextEncoding = value;
            }
        }

        //[DefaultValue(SecurityAlgorithmSuite.Default)] - errors
        public SecurityAlgorithmSuite FedBindingSecurityMessageAlgorithmSuite
        {
            get
            {
                return m_FedBinding.Security.Message.AlgorithmSuite;
            }
            set
            {
                m_FedBinding.Security.Message.AlgorithmSuite = value;
            }
        }

        [DefaultValue(SecurityKeyType.AsymmetricKey)]
        public SecurityKeyType FedBindingSecurityMessageIssuedKeyType
        {
            get
            {
                return m_FedBinding.Security.Message.IssuedKeyType;
            }
            set
            {
                m_FedBinding.Security.Message.IssuedKeyType = value;
            }
        }

        public bool FedBindingSecurityMessageNegotiateServiceCredential
        {
            get
            {
                return m_FedBinding.Security.Message.NegotiateServiceCredential;
            }
            set
            {
                m_FedBinding.Security.Message.NegotiateServiceCredential = value;
            }
        }
        
        public int FedBindingCloseTimeout
        {
            get
            {
                return m_FedBinding.CloseTimeout.Minutes;
            }
            set
            {
                m_FedBinding.CloseTimeout = TimeSpan.FromMinutes(value);
            }
        }

        public int FedBindingOpenTimeout
        {
            get
            {
                return m_FedBinding.OpenTimeout.Minutes;
            }
            set
            {
                m_FedBinding.OpenTimeout = TimeSpan.FromMinutes(value);
            }
        }

        public int FedBindingReceiveTimeout
        {
            get
            {
                return m_FedBinding.ReceiveTimeout.Minutes;
            }
            set
            {
                m_FedBinding.ReceiveTimeout = TimeSpan.FromMinutes(value);
            }
        }

        public int FedBindingSendTimeout
        {
            get
            {
                return m_FedBinding.SendTimeout.Minutes;
            }
            set
            {
                m_FedBinding.SendTimeout = TimeSpan.FromMinutes(value);
            }
        }

        public bool FedBindingBypassProxyOnLocal
        {
            get
            {
                return m_FedBinding.BypassProxyOnLocal;
            }
            set
            {
                m_FedBinding.BypassProxyOnLocal = value;
            }
        }

        public bool FedBindingTransactionFlow
        {
            get
            {
                return m_FedBinding.TransactionFlow;
            }
            set
            {
                m_FedBinding.TransactionFlow = value;
            }
        }

        public long FedBindingMaxBufferPoolSize
        {
            get
            {
                return m_FedBinding.MaxBufferPoolSize;
            }
            set
            {
                m_FedBinding.MaxBufferPoolSize = value;
            }
        }

        public long FedBindingMaxReceivedMessageSize
        {
            get
            {
                return m_FedBinding.MaxReceivedMessageSize;
            }
            set
            {
                m_FedBinding.MaxReceivedMessageSize = value;
            }
        }

        public bool FedBindingUseDefaultWebProxy
        {
            get
            {
                return m_FedBinding.UseDefaultWebProxy;
            }
            set
            {
                m_FedBinding.UseDefaultWebProxy = value;
            }
        }

        public int FedBindingReaderQuotasMaxDepth
        {
            get
            {
                return m_FedBinding.ReaderQuotas.MaxDepth;
            }
            set
            {
                m_FedBinding.ReaderQuotas.MaxDepth = value;
            }
        }

        public int FedBindingReaderQuotasMaxStringContentLength
        {
            get
            {
                return m_FedBinding.ReaderQuotas.MaxStringContentLength;
            }
            set
            {
                m_FedBinding.ReaderQuotas.MaxStringContentLength = value;
            }
        }

        public int FedBindingReaderQuotasMaxArrayLength
        {
            get
            {
                return m_FedBinding.ReaderQuotas.MaxArrayLength;
            }
            set
            {
                m_FedBinding.ReaderQuotas.MaxArrayLength = value;
            }
        }

        public int FedBindingReaderQuotasMaxBytesPerRead
        {
            get
            {
                return m_FedBinding.ReaderQuotas.MaxBytesPerRead;
            }
            set
            {
                m_FedBinding.ReaderQuotas.MaxBytesPerRead = value;
            }
        }

        public int FedBindingReaderQuotasMaxNameTableCharCount
        {
            get
            {
                return m_FedBinding.ReaderQuotas.MaxNameTableCharCount;
            }
            set
            {
                m_FedBinding.ReaderQuotas.MaxNameTableCharCount = value;
            }
        }

        public bool FedBindingReliableSessionOrdered
        {
            get
            {
                return m_FedBinding.ReliableSession.Ordered;
            }
            set
            {
                m_FedBinding.ReliableSession.Ordered = value;
            }
        }

        public int FedBindingReliableSessionInactivityTimeout
        {
            get
            {
                return m_FedBinding.ReliableSession.InactivityTimeout.Minutes;
            }
            set
            {
                m_FedBinding.ReliableSession.InactivityTimeout = TimeSpan.FromMinutes(value);
            }
        }

        public bool FedBindingReliableSessionEnabled
        {
            get
            {
                return m_FedBinding.ReliableSession.Enabled;
            }
            set
            {
                m_FedBinding.ReliableSession.Enabled = value;
            }
        }
        //************************************************************************************
        //************************************************************************************
        #endregion

        #region WCF Connect and Display Properties
        //NOTE:  Shortcut properties (i.e. public string foo {get;set;} don't show up in Intellisense
        //WCF properties
        private string m_WcfUrl = string.Empty;
        public string WcfUrl
        {
            get
            {
                return m_WcfUrl;
            }
            set
            {
                m_WcfUrl = value;

                //whenever the Wcf Url is set we want to create a new endpoint address for it
                WcfEndpointAddress = new EndpointAddress(m_WcfUrl);
            }
        }

        private string m_MethodName = string.Empty;
        public string MethodName
        {
            get
            {
                return m_MethodName;
            }
            set
            {
                m_MethodName = value;
            }
        }

        private string m_MethodParams = string.Empty;
        public string MethodParams
        {
            get
            {
                return m_MethodParams;
            }
            set
            {
                m_MethodParams = value;
            }
        }

        //the object that is returned from CreateChannelAsLoggedOnUser
        private object m_WcfClientProxy = null;
        public object WcfClientProxy
        {
            get
            {
                return m_WcfClientProxy;
            }
            set
            {
                m_WcfClientProxy = value;
            }
        }

        //a string representation of the results
        private string m_QueryResultsString = string.Empty;
        public string QueryResultsString
        {
            get
            {
                return m_QueryResultsString;
            }
        }

        //an object representation of the results
        private object m_QueryResultsObject = null;
        public object QueryResultsObject
        {
            get
            {
                return m_QueryResultsObject;
            }
        }


        //how we want the data returned / used
        private DataOutputType m_OutputType = DataOutputType.Page;
        public DataOutputType OutputType
        {
            get
            {
                return m_OutputType;
            }
            set
            {
                m_OutputType = value;
            }
        }

        //what name should we use if storing something in cache; can override with query string
        private string m_ServerCacheName = string.Empty;
        public string ServerCacheName
        {
            get
            {
                return m_ServerCacheName;
            }
            set
            {
                m_ServerCacheName = value;
            }
        }

        //what is the TTL for the server cache item (in minutes)
        private int m_ServerCacheTime = 0;
        public int ServerCacheTime
        {
            get
            {
                return m_ServerCacheTime;
            }
            set
            {
                m_ServerCacheTime = value;
            }
        }

        //whether the return value should be decoded
        private bool m_DecodeResults = false;
        public bool DecodeResults
        {
            get
            {
                return m_DecodeResults;
            }
            set
            {
                m_DecodeResults = value;
            }
        }

        //this is in case the control is created programmatically, there won't be an http context
        //to use for the SharePoint site against which the claims auth token is going to be
        //generated; instead they will just use the value provided here
        private string m_SharePointClaimsSiteUrl = string.Empty;
        public string SharePointClaimsSiteUrl
        {
            get
            {
                return m_SharePointClaimsSiteUrl;
            }
            set
            {
                //if a valid value is passed, trim any trailing slash
                if (!string.IsNullOrEmpty(value))
                    m_SharePointClaimsSiteUrl = value.EndsWith("/") ? value.Remove(value.Length - 1, 1) : value;
                else
                    m_SharePointClaimsSiteUrl = value;
            }
        }

        //this property will give farm admins the ability to lock down the methods that can
        //be called via a data page.  By setting this property to false, any query string
        //properties that are passed along will be ignored
        private bool m_AllowQueryStringOverride = true;
        public bool AllowQueryStringOverride
        {
            get
            {
                return m_AllowQueryStringOverride;
            }
            set
            {
                m_AllowQueryStringOverride = value;
            }
        }

        //this can be used as a general error message to display when
        //the method cannot be executed because of an Access Denied issue, 
        //such as a PrincipalPermission demand that is not met with the
        //current user's credentials
        private string m_AccessDeniedMessage = string.Empty;
        public string AccessDeniedMessage
        {
            get
            {
                return m_AccessDeniedMessage;
            }
            set
            {
                m_AccessDeniedMessage = value;
            }
        }

        //this is the message we'll use when there is a timeout
        private string m_TimeoutMessage = string.Empty;
        public string TimeoutMessage
        {
            get
            {
                return m_TimeoutMessage;
            }
            set
            {
                m_TimeoutMessage = value;
            }
        }

		//these are properties that are used for troubleshooting and debugging

		private bool m_ReturnDiagnosticsInformation = true;
		public bool ReturnDiagnosticsInformation
		{
			get
			{
				return m_ReturnDiagnosticsInformation;
			}
			set
			{
				m_ReturnDiagnosticsInformation = value;
			}
		}

		//the name of the server where the code executes; in case you need to look at the ULS logs
		private string m_ExecutionServerName = string.Empty;
		public string ExecutionServerName
		{
			get
			{
				return m_ExecutionServerName;
			}
			set
			{
				m_ExecutionServerName = value;
			}
		}

		//any error messages that were returned
		private string m_ExecutionErrorMessage = string.Empty;
		public string ExecutionErrorMessage
		{
			get
			{
				return m_ExecutionErrorMessage;
			}
			set
			{
				m_ExecutionErrorMessage = value;
			}
		}

		//trace info regarding the variables that were passed, method called, and execution time
		private string m_TraceInfoMessage = string.Empty;
		public string TraceInfoMessage
		{
			get
			{
				return m_TraceInfoMessage;
			}
			set
			{
				m_TraceInfoMessage = value;
			}
		}
        #endregion


        //CHANGED THIS FROM OVERRIDE OF OnInit BECAUSE IT WON'T FIRE WHEN THE
        //CONTROL IS CREATED PROGRAMMATICALLY, AND ALL THINGS OCCURRING IN THIS
        //CODE DON'T REQUIRE PROPERTY VALUES FROM THE SERVER TAG OR SET PROGRAMMATICALLY
        public WcfConfig()
        {
            try
            {
                //create our controls and set default properties
                #region SecurityBinding Properties
                ////set up the customBinding first; it is used in the ws2007FederationHttpBinding
                //m_SecurityBinding.IncludeTimestamp = true;
                //m_SecurityBinding.DefaultAlgorithmSuite = SecurityAlgorithmSuite.Basic256Sha256;
                //m_SecurityBinding.SecurityHeaderLayout = SecurityHeaderLayout.Strict;
                //m_SecurityBinding.KeyEntropyMode = SecurityKeyEntropyMode.CombinedEntropy;
                #endregion
                m_SecurityBinding.SetKeyDerivation(false);
                m_SecurityBinding.MessageSecurityVersion =
                    MessageSecurityVersion.WSSecurity11WSTrust13WSSecureConversation13WSSecurityPolicy12BasicSecurityProfile10;

                #region Local Client Settings
                ////configure the local client settings
                //m_SecurityBinding.LocalClientSettings.CacheCookies = true;
                //m_SecurityBinding.LocalClientSettings.DetectReplays = false;
                //m_SecurityBinding.LocalClientSettings.ReplayCacheSize = 900000;
                //m_SecurityBinding.LocalClientSettings.MaxClockSkew = TimeSpan.FromMinutes(5);
                //m_SecurityBinding.LocalClientSettings.MaxCookieCachingTime = TimeSpan.MaxValue;
                //m_SecurityBinding.LocalClientSettings.ReplayWindow = TimeSpan.FromMinutes(5);
                //m_SecurityBinding.LocalClientSettings.SessionKeyRenewalInterval = TimeSpan.FromMinutes(10);
                //m_SecurityBinding.LocalClientSettings.SessionKeyRolloverInterval = TimeSpan.FromMinutes(5);
                //m_SecurityBinding.LocalClientSettings.ReconnectTransportOnFailure = true;
                //m_SecurityBinding.LocalClientSettings.TimestampValidityDuration = TimeSpan.FromMinutes(5);
                //m_SecurityBinding.LocalClientSettings.CookieRenewalThresholdPercentage = 60;
                #endregion

                #region Local Service Settings
                ////set the local Service setttings
                //m_SecurityBinding.LocalServiceSettings.DetectReplays = false;
                //m_SecurityBinding.LocalServiceSettings.IssuedCookieLifetime = TimeSpan.FromMinutes(10);
                //m_SecurityBinding.LocalServiceSettings.MaxStatefulNegotiations = 128;
                //m_SecurityBinding.LocalServiceSettings.ReplayCacheSize = 900000;
                //m_SecurityBinding.LocalServiceSettings.MaxClockSkew = TimeSpan.FromMinutes(5);
                //m_SecurityBinding.LocalServiceSettings.NegotiationTimeout = TimeSpan.FromMinutes(1);
                //m_SecurityBinding.LocalServiceSettings.ReplayWindow = TimeSpan.FromMinutes(5);
                //m_SecurityBinding.LocalServiceSettings.InactivityTimeout = TimeSpan.FromMinutes(2);
                //m_SecurityBinding.LocalServiceSettings.SessionKeyRenewalInterval = TimeSpan.FromMinutes(15);
                //m_SecurityBinding.LocalServiceSettings.SessionKeyRolloverInterval = TimeSpan.FromMinutes(5);
                //m_SecurityBinding.LocalServiceSettings.ReconnectTransportOnFailure = true;
                //m_SecurityBinding.LocalServiceSettings.MaxPendingSessions = 128;
                //m_SecurityBinding.LocalServiceSettings.MaxCachedCookies = 1000;
                //m_SecurityBinding.LocalServiceSettings.TimestampValidityDuration = TimeSpan.FromMinutes(5);
                #endregion

                #region BinaryMessage Settings
                ////create the binary message encoding element
                //m_BinaryMessage.MaxReadPoolSize = 64;
                //m_BinaryMessage.MaxWritePoolSize = 16;
                //m_BinaryMessage.MaxSessionSize = 2048;
                //m_BinaryMessage.ReaderQuotas.MaxDepth = 32;
                //m_BinaryMessage.ReaderQuotas.MaxStringContentLength = 131072;  //changed from 8192
                //m_BinaryMessage.ReaderQuotas.MaxArrayLength = 16384;
                //m_BinaryMessage.ReaderQuotas.MaxBytesPerRead = 4096;
                //m_BinaryMessage.ReaderQuotas.MaxNameTableCharCount = 16384;
                #endregion

                #region HttpsTransport Settings
                ////create the HTTPS transport element
                //m_SecureTransport.ManualAddressing = false;
                //m_SecureTransport.MaxBufferPoolSize = 524288;
                //m_SecureTransport.MaxReceivedMessageSize = 65536;
                //m_SecureTransport.AllowCookies = false;
                //m_SecureTransport.BypassProxyOnLocal = false;
                ////decompressionEnabled ???  -- Requires .NET 4.x
                //m_SecureTransport.KeepAliveEnabled = true;
                //m_SecureTransport.MaxBufferSize = 65536;
                //m_SecureTransport.Realm = "";
                //m_SecureTransport.UnsafeConnectionNtlmAuthentication = false;
                //m_SecureTransport.UseDefaultWebProxy = true;
                //m_SecureTransport.RequireClientCertificate = false;
                //m_SecureTransport.AuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
                //m_SecureTransport.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
                //m_SecureTransport.ProxyAuthenticationScheme = System.Net.AuthenticationSchemes.Anonymous;
                //m_SecureTransport.TransferMode = TransferMode.Buffered;
                #endregion

                #region FedBinding Settings
                ////now create the wsFed binding
                //m_FedBinding.CloseTimeout = TimeSpan.FromMinutes(1);
                //m_FedBinding.OpenTimeout = TimeSpan.FromMinutes(1);
                //m_FedBinding.ReceiveTimeout = TimeSpan.FromMinutes(10);
                //m_FedBinding.SendTimeout = TimeSpan.FromMinutes(1);
                //m_FedBinding.BypassProxyOnLocal = false;
                //m_FedBinding.TransactionFlow = false;
                //m_FedBinding.MaxBufferPoolSize = 524288;
                //m_FedBinding.MaxReceivedMessageSize = 65536;
                //m_FedBinding.UseDefaultWebProxy = true;
                //m_FedBinding.ReaderQuotas.MaxDepth = 32;
                //m_FedBinding.ReaderQuotas.MaxStringContentLength = 131072; //changed from 8192
                //m_FedBinding.ReaderQuotas.MaxArrayLength = 16384;
                //m_FedBinding.ReaderQuotas.MaxBytesPerRead = 4096;
                //m_FedBinding.ReaderQuotas.MaxNameTableCharCount = 16384;
                //m_FedBinding.ReliableSession.Ordered = true;
                //m_FedBinding.ReliableSession.InactivityTimeout = TimeSpan.FromMinutes(10);
                //m_FedBinding.ReliableSession.Enabled = false;
                //m_FedBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
                //m_FedBinding.MessageEncoding = WSMessageEncoding.Text;
                //m_FedBinding.TextEncoding = System.Text.Encoding.UTF8;

                //set up the security mode
                //m_FedBinding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
                //m_FedBinding.Security.Message.IssuedKeyType = SecurityKeyType.AsymmetricKey;
                //m_FedBinding.Security.Message.NegotiateServiceCredential = true;
                #endregion

                //THIS MUST BE TransportWithMessageCredential OR THE CALL WILL FAIL WITH HTTPS
                m_FedBinding.Security.Mode = WSFederationHttpSecurityMode.TransportWithMessageCredential;

                //MOVING ALL OF THIS TO OUR EXECUTE METHOD SO WE CAN BE SURE THE PROPERTY VALUES
                //HAVE BEEN SET FOR SHAREPOINTCLAIMSSITEURL BEFORE EXECUTING
                #region Set Issuer Address
                ////add all the bindings to a list
                //BindingElementCollection bec = new BindingElementCollection();
                //bec.Add(m_SecurityBinding);
                //bec.Add(m_BinaryMessage);
                //bec.Add(m_SecureTransport);

                ////now create the custom binding
                //CustomBinding cb = new CustomBinding(bec);
//                //get the scheme (https or http), host and port number of the request so we can 
//                //look for the STS stuff in the layouts directory of the current request
//                string rootUrl = string.Empty;

//                //see if a value was provided for the SharePointClaimsSiteUrl property 
//                //and use it if it was
//                if (!string.IsNullOrEmpty(SharePointClaimsSiteUrl))
//                    //use the property value;
//                    rootUrl = SharePointClaimsSiteUrl;
//                else
//                {
//                    if (HttpContext.Current != null)
//                    {
//                        Uri rqst = HttpContext.Current.Request.Url;
//                        rootUrl = rqst.Scheme + "://" + rqst.Host + ":" + rqst.Port;
//                    }
//                }

//#if DEBUG
//                rootUrl = "https://fc1";
//#endif

//                //windows or cookie
//                //for example, 
//                //"https://fc1/_vti_bin/sts/spsecuritytokenservice.svc/cookie"
//                m_FedBinding.Security.Message.IssuerAddress =
//                    new EndpointAddress(rootUrl + "/_vti_bin/sts/spsecuritytokenservice.svc/cookie");

//                m_FedBinding.Security.Message.IssuerBinding = cb;

//                //for example,
//                //"https://fc1/_vti_bin/sts/spsecuritytokenservice.svc?wsdl"
//                m_FedBinding.Security.Message.IssuerMetadataAddress =
//                  new EndpointAddress(rootUrl + "/_vti_bin/sts/spsecuritytokenservice.svc?wsdl");
                #endregion

                //add the TokenRequestParameters, which are all just XmlElement instances

                //create the secondaryParameters root node:  trust:SecondaryParameters
                XmlDocument xDoc = new XmlDocument();
                XmlElement xTrust = xDoc.CreateElement("trust:SecondaryParameters", trustNS);

                xTrust.AppendChild(GetTokenNode(xDoc, "KeyType",
                    "http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey"));

                xTrust.AppendChild(GetTokenNode(xDoc, "KeyWrapAlgorithm",
                    "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"));

                xTrust.AppendChild(GetTokenNode(xDoc, "EncryptWith",
                    "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"));

                xTrust.AppendChild(GetTokenNode(xDoc, "SignWith",
                    "http://www.w3.org/2000/09/xmldsig#rsa-sha1"));

                xTrust.AppendChild(GetTokenNode(xDoc, "CanonicalizationAlgorithm",
                    "http://www.w3.org/2001/10/xml-exc-c14n#"));

                xTrust.AppendChild(GetTokenNode(xDoc, "EncryptionAlgorithm",
                    "http://www.w3.org/2001/04/xmlenc#aes256-cbc"));

                //add the nodes
                m_FedBinding.Security.Message.TokenRequestParameters.Add
                    (xTrust.CloneNode(true) as XmlElement);

                m_FedBinding.Name = "WS2007FederationHttpBinding_SharePoint";

				#region Override Minimum Default Properties
				if (m_BinaryMessage.ReaderQuotas.MaxStringContentLength < MAX_CONTENT_LENGTH)
					BinaryMessageReaderQuotasMaxStringContentLength = MAX_CONTENT_LENGTH;

				if (m_FedBinding.ReaderQuotas.MaxStringContentLength < MAX_CONTENT_LENGTH)
					m_FedBinding.ReaderQuotas.MaxStringContentLength = MAX_CONTENT_LENGTH;

				if ((m_FedBinding.SendTimeout.Seconds == 0) || (m_FedBinding.SendTimeout.Seconds > MAX_REQUEST_ON_WIRE_TIMEOUT))
					m_FedBinding.SendTimeout = TimeSpan.FromSeconds(MAX_REQUEST_ON_WIRE_TIMEOUT);

				if ((m_SecurityBinding.LocalServiceSettings.InactivityTimeout.Seconds == 0) ||
					(m_SecurityBinding.LocalServiceSettings.InactivityTimeout.Seconds > MAX_REQUEST_ON_WIRE_TIMEOUT))
					m_SecurityBinding.LocalServiceSettings.InactivityTimeout = TimeSpan.FromSeconds(MAX_REQUEST_ON_WIRE_TIMEOUT);

				if ((m_FedBinding.ReceiveTimeout.Seconds == 0) || (m_FedBinding.ReceiveTimeout.Seconds > MAX_REQUEST_ON_WIRE_TIMEOUT))
					m_FedBinding.ReceiveTimeout = TimeSpan.FromSeconds(MAX_REQUEST_ON_WIRE_TIMEOUT);
				#endregion
            }
            catch (Exception ex)
            {
                Log.WriteLog("Error during OnInit in WCF configuration control: " +
                    ex.Message, Log.LogTypes.Both, TraceSeverity.High, EventSeverity.ErrorCritical);
            }     
        }


        public virtual bool ExecuteRequest()
        {
			bool results = true;

			using (SPMonitoredScope er = new SPMonitoredScope("AzureConnect_ExecuteRequest"))
			{
				try
				{
					//create the divs in the page into which results will be put
					div = new HtmlGenericControl("DIV");
					div.Attributes.Add("id", RESPONSE_DIV_ID);

					serverNameDiv = new HtmlGenericControl("DIV");
					serverNameDiv.Attributes.Add("id", SERVERNAME_DIV_ID);

					errorMsgDiv = new HtmlGenericControl("DIV");
					errorMsgDiv.Attributes.Add("id", ERRORMESSAGE_DIV_ID);

					traceInfoDiv = new HtmlGenericControl("DIV");
					traceInfoDiv.Attributes.Add("id", TRACEINFO_DIV_ID);

					//plug in the server name here
					ExecutionServerName = Environment.MachineName;

					//get the operation type so we know if cache properties are required
					if ((HttpContext.Current != null) && (AllowQueryStringOverride))
					{
						//put in a separate try block in case a bogus value is passed in
						try
						{
							if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_OUTPUTTYPE]))
								OutputType = (DataOutputType)Enum.Parse(OutputType.GetType(),
												HttpContext.Current.Request.QueryString[QUERYSTRING_OUTPUTTYPE],
												true);
						}
						catch
						{
							//ignore
						}

					}

					//used to store the data we'll write out
					string data = string.Empty;

					//parameters used to track the ASP.NET cache name and duration
					string cacheName = string.Empty;
					int cacheTime = 0;

					//flag to check whether there was an access denied error
					bool wasAccessError = false;

					//first check to see if the OutputType is Server or Both, or if the Page
					//context is null but HttpContext isn't, which means that this control 
					//instance is being instantiated programmatically instead of being called
					// via an async request for the custom _layouts page; if so we
					//need to enforce caching parameters and try looking for the data
					//in cache
					if (
						(OutputType == DataOutputType.ServerCache) ||
						(OutputType == DataOutputType.Both) ||
						((this.Page == null) && (HttpContext.Current != null))
						)
					{
						//now look for cache properties
						if ((HttpContext.Current != null) && (AllowQueryStringOverride))
						{
							if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_SERVERCACHENAME]))
								cacheName = HttpContext.Current.Request.QueryString[QUERYSTRING_SERVERCACHENAME];
						}

						if (string.IsNullOrEmpty(cacheName))
							if (!string.IsNullOrEmpty(ServerCacheName))
								cacheName = ServerCacheName;

						if ((HttpContext.Current != null) && (AllowQueryStringOverride))
						{
							if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_SERVERCACHETIME]))
								int.TryParse(
									HttpContext.Current.Request.QueryString[QUERYSTRING_SERVERCACHETIME],
									out cacheTime);
						}

						if (cacheTime < MIN_SERVER_CACHE_TIME)
							if (ServerCacheTime > MIN_SERVER_CACHE_TIME)
								cacheTime = ServerCacheTime;
							else
								cacheTime = MIN_SERVER_CACHE_TIME;

						//if the OutputType is either Server or Both, or the current
						//Page instance is null (because the control is being used 
						//programmatically) then the cache name and time are required
						if (
							(OutputType == DataOutputType.ServerCache) ||
							(OutputType == DataOutputType.Both) ||
							((this.Page == null) && (HttpContext.Current != null))
							)
						{
							if (string.IsNullOrEmpty(cacheName))
								throw new ArgumentNullException("ServerCacheName");
							if (cacheTime == 0)
								throw new ArgumentNullException("ServerCacheTime");
						}

						//if we are using server cache then look for the content first in there
						if (HttpContext.Current != null)
						{
							if (HttpContext.Current.Cache[ServerCacheName] != null)
							{
								//store the cached item in our object results
								m_QueryResultsObject = HttpContext.Current.Cache[ServerCacheName];

								//retrieve the item from cache
								data = GetDataFromReturnedObject();

								//set all the logging and debug info
								string logResults = "Data retrieved from cache using cache key " +
									ServerCacheName;

								Log.WriteLog(logResults, Log.LogTypes.UlsLog, 
									TraceSeverity.Verbose, EventSeverity.Information);
								TraceInfoMessage = logResults;
							}
						}
					}

					//if we don't have any data yet then try retrieving it here
					if (string.IsNullOrEmpty(data))
					{
						//add all the bindings to a list
						BindingElementCollection bec = new BindingElementCollection();
						bec.Add(m_SecurityBinding);
						bec.Add(m_BinaryMessage);
						bec.Add(m_SecureTransport);

						//now create the custom binding
						CustomBinding cb = new CustomBinding(bec);

						//get the scheme (https or http), host and port number of the request so we can 
						//look for the STS stuff in the layouts directory of the current request
						string rootUrl = string.Empty;

						//see if a value was provided for the SharePointClaimsSiteUrl property 
						//and use it if it was
						if (!string.IsNullOrEmpty(SharePointClaimsSiteUrl))
							//use the property value;
							rootUrl = SharePointClaimsSiteUrl;
						else
						{
							if (HttpContext.Current != null)
							{
								Uri rqst = HttpContext.Current.Request.Url;
								rootUrl = rqst.Scheme + "://" + rqst.Host + ":" + rqst.Port;
							}
						}

#if DEBUG
						//rootUrl = "https://fc1";
#endif

						Log.WriteLog("Root Url for SharePoint STS endpoint set to " + rootUrl,
							Log.LogTypes.UlsLog, TraceSeverity.Verbose, EventSeverity.Information);

						//windows or cookie
						//for example, 
						//"https://fc1/_vti_bin/sts/spsecuritytokenservice.svc/cookie"
						m_FedBinding.Security.Message.IssuerAddress =
							new EndpointAddress(rootUrl + "/_vti_bin/sts/spsecuritytokenservice.svc/cookie");

						m_FedBinding.Security.Message.IssuerBinding = cb;

						//for example,
						//"https://fc1/_vti_bin/sts/spsecuritytokenservice.svc?wsdl"
						m_FedBinding.Security.Message.IssuerMetadataAddress =
							new EndpointAddress(rootUrl + "/_vti_bin/sts/spsecuritytokenservice.svc?wsdl");

						//make sure the type instance we'll use to call methods is set
						//we'll do a GetType and then use the Type instance to call methods
						if (WcfClientProxy == null)
							throw new MissingMemberException("The WcfClientProxy property has not been set " +
								"to the return value from the " +
								"SPChannelFactoryOperations.CreateChannelActingAsLoggedOnUser " +
								"method call.");

						//from query string or MethodName property
						string methodName = string.Empty;
						if ((HttpContext.Current != null) && (AllowQueryStringOverride))
						{
							if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_METHODNAME]))
								methodName = HttpContext.Current.Request.QueryString[QUERYSTRING_METHODNAME];
						}

						//check in this way, in this order, so that the default values can be overridden
						//by passing in query string parameters for property values
						if (string.IsNullOrEmpty(methodName))
							if (!string.IsNullOrEmpty(MethodName))
								methodName = MethodName;

						//from query string or MethodParams property - dump into array using semi-colon delim
						string methodParams = string.Empty;
						if ((HttpContext.Current != null) && (AllowQueryStringOverride))
						{
							if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_METHODPARAMS]))
								methodParams = HttpContext.Current.Request.QueryString[QUERYSTRING_METHODPARAMS];
						}

						if (string.IsNullOrEmpty(methodParams))
							if (!string.IsNullOrEmpty(MethodParams))
								methodParams = MethodParams;

						//do a check now to make sure that all required properties have been set; if not
						//throw a MissingParametersException
						if (string.IsNullOrEmpty(rootUrl))
							throw new ArgumentNullException("SharePointClaimsSiteUrl");
						if (string.IsNullOrEmpty(methodName))
							throw new ArgumentNullException("MethodName");
						if (string.IsNullOrEmpty(WcfUrl))
							throw new ArgumentNullException("WcfUrl");

						//check for decoding results
						if ((HttpContext.Current != null) && (AllowQueryStringOverride))
						{
							//put in a separate try block in case a bogus value is passed in
							try
							{
								if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_DECODERESULTS]))
								{
									bool decode = DecodeResults;

									bool.TryParse(
										HttpContext.Current.Request.QueryString[QUERYSTRING_DECODERESULTS],
										out decode);
									DecodeResults = decode;
								}
							}
							catch
							{
								//ignore
							}
						}

						//the access denied message that should be used
						string accessDenied = string.Empty;
						if ((HttpContext.Current != null) && (AllowQueryStringOverride))
						{
							if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_ACCESSDENIEDMSG]))
								accessDenied = HttpContext.Current.Request.QueryString[QUERYSTRING_ACCESSDENIEDMSG];
						}

						if (string.IsNullOrEmpty(accessDenied))
							if (!string.IsNullOrEmpty(AccessDeniedMessage))
								accessDenied = AccessDeniedMessage;

						//the timeout message that should be used
						string timeoutMsg = string.Empty;
						if ((HttpContext.Current != null) && (AllowQueryStringOverride))
						{
							if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[QUERYSTRING_TIMEOUTMSG]))
								timeoutMsg = HttpContext.Current.Request.QueryString[QUERYSTRING_TIMEOUTMSG];
						}

						if (string.IsNullOrEmpty(timeoutMsg))
							if (!string.IsNullOrEmpty(TimeoutMessage))
								timeoutMsg = TimeoutMessage;

						//capture all of the parameters used and write to ULS if doing verboes logging
						StringBuilder sbParams = new StringBuilder(1024);
						sbParams.Append("SharePointClaimsSiteUrl=" + rootUrl + "; ");
						sbParams.Append("WcfClientProxy Type=" + WcfClientProxy.GetType().ToString() + "; ");
						sbParams.Append("MethodName=" + methodName + "; ");
						sbParams.Append("MethodParams=" + methodParams + "; ");
						sbParams.Append("WcfUrl=" + WcfUrl + "; ");
						sbParams.Append("ServerCacheName=" + cacheName + "; ");
						sbParams.Append("ServerCacheTime=" + cacheTime.ToString() + "; ");
						sbParams.Append("OutputType=" + OutputType.ToString() + "; ");
						sbParams.Append("DecodeResults=" + DecodeResults.ToString() + "; ");
						sbParams.Append("TimeoutMessage=" + timeoutMsg + "; ");
						sbParams.Append("AccessDeniedMessage=" + accessDenied);

						Log.WriteLog("The following properties were used to execute this request: " +
							sbParams.ToString(), Log.LogTypes.UlsLog, TraceSeverity.Medium,
							EventSeverity.Information);

						//add this to the trace info
						TraceInfoMessage = sbParams.ToString();

						//all present and accounted for so execute method call
						Type t = WcfClientProxy.GetType();

						//get method params if any; requires the client proxy to get parameter type info
						int paramCount = 0;
						object[] parms = new object[paramCount];

						if (!string.IsNullOrEmpty(methodParams))
						{
							string[] parmValues =
								methodParams.Split(";".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

							//reset vars
							paramCount = parmValues.Count();
							parms = new object[paramCount];

							//get the method and param info so the correct types
							//can be used for the method parameters; if you don't 
							//add the params with the correct type then an error
							//will be thrown saying the method name can't be found
							MethodInfo mi = t.GetMethod(MethodName);
							ParameterInfo[] parmsInfo = mi.GetParameters();

							//counter for key into array
							int i = 0;

							foreach (ParameterInfo pi in parmsInfo)
							{
								if (pi.ParameterType == typeof(int))
									parms[i] = int.Parse(parmValues[i]);
								else if (pi.ParameterType == typeof(long))
									parms[i] = long.Parse(parmValues[i]);
								else if (pi.ParameterType == typeof(bool))
									parms[i] = bool.Parse(parmValues[i]);
								else if (pi.ParameterType == typeof(DateTime))
									parms[i] = DateTime.Parse(parmValues[i]);
								else
									//default data type - string
									parms[i] = parmValues[i];

								//increment the index into the value array
								i += 1;
							}
						}

						Log.WriteLog("Making WCF call to " + WcfUrl, Log.LogTypes.UlsLog,
							TraceSeverity.Verbose, EventSeverity.Information);

						//create a stopwatch to track the execution time
						Stopwatch swatch = new Stopwatch();
						swatch.Start();

						//put in a separate try block to filter access denied errors
						try
						{
							m_QueryResultsObject =
								t.InvokeMember(methodName,
									BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance,
									null,
									WcfClientProxy,
									parms);
						}
						catch (Exception invokeEx)
						{

							if ((invokeEx.InnerException != null) && (invokeEx.InnerException.GetType() == typeof(System.ServiceModel.Security.SecurityAccessDeniedException)))
							{
								//add access denied message here
								data = accessDenied;
								wasAccessError = true;
								ExecutionErrorMessage += invokeEx.Message;
							}
							else if ((invokeEx.InnerException != null) && (invokeEx.InnerException.GetType() == typeof(System.TimeoutException)))
							{
								//add timeout error message here
								data = timeoutMsg;
								wasAccessError = true;
								ExecutionErrorMessage += invokeEx.Message;
							}
							else if (invokeEx.GetType() == typeof(System.MissingMethodException))
							{
								throw new Exception("Method name was missing or incorrect.  Make sure " +
									"a method named " + methodName + " exists in the WCF application " +
									"and also that the name is using the correct case.  Calling a " +
									"method where the name does not match the case of the method " +
									"name in the WCF application will cause this error to occur.");
							}
							else if (invokeEx.InnerException != null)
							{
								if (
									(invokeEx.InnerException.GetType() == typeof(System.ServiceModel.Security.MessageSecurityException)) &&
									(invokeEx.InnerException.InnerException != null)
									)
								{
									//in this case, we're saying if we get an exception, and the inner
									//exception is the infamous "An unsecured or incorrectly secured 
									//fault was received from the other party" error message, then 
									//look to see if it has an inner exception to it that might provide
									//more details to the security exception
									throw new Exception("An error occurred because an unsecured or " +
										"incorrectly secured fault was received from the other party; " +
										"the inner exception for this error was: " +
										invokeEx.InnerException.InnerException.Message);
								}
								else
									throw new Exception("An error occurred invoking the request; the " +
										"inner exception was: " + invokeEx.InnerException.Message); // +
								//"and its stack trace was " + invokeEx.InnerException.StackTrace);
								//stack trace seems like too much information
							}
							else
								//all other errors just toss it back up through the method's error handling
								throw;  //throwing without an argument to preserve the call stack: invokeEx;
						}

						try
						{
							//close the channel; otherwise you will hit the MaxConcurrentSessions
							//and all subsequent calls will time out
							IChannel wcf = (IChannel)WcfClientProxy;
							wcf.Close();
						}
						catch
						{
							//ignore
						}

						swatch.Stop();
						string connectInfo = "AzureConnect took " + swatch.ElapsedMilliseconds.ToString() +
							" milliseconds to complete WCF call to " + WcfUrl;
						Log.WriteLog(connectInfo, Log.LogTypes.UlsLog, TraceSeverity.Medium,
							EventSeverity.Information);
						TraceInfoMessage += Environment.NewLine + connectInfo;

						//if there was an access denied error then the rest of the process can be skipped
						if (!wasAccessError)
						{
							//make sure we got a valid return value
							if (m_QueryResultsObject != null)
							{
								//get the consumable data from the return object
								data = GetDataFromReturnedObject();
							}
							else
							{
								string dataReturnInfo = "The return value from the call to " + WcfUrl +
									" was null.";
								Log.WriteLog(dataReturnInfo, Log.LogTypes.UlsLog, 
									TraceSeverity.Verbose, EventSeverity.Information);
								ExecutionErrorMessage += dataReturnInfo;
							}

							//if the data is supposed to be stored in cache, then do it here
							if ((OutputType == DataOutputType.Both) || (OutputType == DataOutputType.ServerCache))
							{
								//make sure we have some http context
								if (HttpContext.Current != null)
								{
									HttpContext.Current.Cache.Insert(cacheName, m_QueryResultsObject,
										null, DateTime.Now.AddMinutes(cacheTime),
										System.Web.Caching.Cache.NoSlidingExpiration);

									Log.WriteLog("Results added to Http Cache for " +
										cacheTime.ToString() + " minutes.", Log.LogTypes.UlsLog,
										TraceSeverity.Verbose, EventSeverity.Information);
								}
							}
						}
						else
						{
							if (data == timeoutMsg)
								Log.WriteLog("A timeout error occurred retrieving the data for " +
									WcfUrl, Log.LogTypes.UlsLog, TraceSeverity.Medium,
									EventSeverity.Warning);
							else
								Log.WriteLog("An access denied was returned when requesting data from " +
									WcfUrl, Log.LogTypes.UlsLog, TraceSeverity.Medium,
									EventSeverity.Warning);
						}
					}

					//this must be set even if there's an access denied so the message can
					//percolate back up to the calling code
					//store the string representation of the data; decode if necessary
					if ((DecodeResults) && (!wasAccessError))
						m_QueryResultsString = HttpUtility.HtmlDecode(data);
					else
						m_QueryResultsString = data;
				}
				catch (Exception ex)
				{
					try
					{
						ExecutionErrorMessage += ex.Message;
						results = false;
						Log.WriteLog("Error during ExecuteQuery in WCF configuration control: " +
							ex.Message, Log.LogTypes.Both, TraceSeverity.High, 
							EventSeverity.ErrorCritical);
					}
					catch
					{
						//ignore
					}
				}
			}

			return results;
        }


		private string GetDataFromReturnedObject()
		{
			string results = string.Empty;

			//look at the return data type; if it isn't string, int, bool, long, or datetime
			//then we need to unwrap it by using serialization
			Type returnType = m_QueryResultsObject.GetType();

			if (
				(returnType == typeof(string)) ||
				(returnType == typeof(int)) ||
				(returnType == typeof(bool)) ||
				(returnType == typeof(long)) ||
				(returnType == typeof(DateTime))
				)
				results = m_QueryResultsObject.ToString();
			else
			{
				XmlSerializer x = new XmlSerializer(returnType);
				StringWriter sw = new StringWriter();
				x.Serialize(sw, m_QueryResultsObject);
				results = sw.ToString();
				sw.Close();
				sw.Dispose();
			}

			return results;
		}


        protected override void OnPreRender(EventArgs e)
        {
            try
            {
                base.OnPreRender(e);

                //call the method to execute the query 
                ExecuteRequest();
            }
            catch (Exception ex)
            {
                Log.WriteLog("Error during PreRender in WCF configuration control: " +
                    ex.Message, Log.LogTypes.Both, TraceSeverity.High, EventSeverity.ErrorCritical);
                throw ex;
            }
        }

        protected override void Render(System.Web.UI.HtmlTextWriter writer)
        {
            try
            {
                //shouldn't be anything to show per se, but call the base Render method
                base.Render(writer);

                //if the OutputType is Page or Both then write it out
                if ((OutputType == DataOutputType.Both) || (OutputType == DataOutputType.Page))
                {
                    //plug the results into the div
                    //YOU MUST PLUG IT INTO THE InnerHTML OR RESULTS WILL BE HOPELESSLY ENCODED
                    //THIS WORKS FOR BOTH HTML AND XML
                    div.InnerHtml = QueryResultsString;

					//if we're allowed to return diagnostics info then plug it into the 
					//appropriate divs here
					if (ReturnDiagnosticsInformation)
					{
						serverNameDiv.InnerHtml = ExecutionServerName;
						errorMsgDiv.InnerHtml = ExecutionErrorMessage;
						traceInfoDiv.InnerHtml = TraceInfoMessage;
					}

                    //write out the controls and contents
					div.RenderControl(writer);
					serverNameDiv.RenderControl(writer);
					errorMsgDiv.RenderControl(writer);
					traceInfoDiv.RenderControl(writer);
                }
            }
            catch (Exception ex)
            {
                Log.WriteLog("Error during Render in WCF configuration control: " +
                    ex.Message, Log.LogTypes.Both, TraceSeverity.High, EventSeverity.ErrorCritical);
                throw ex;
            }
        }


        private XmlNode GetTokenNode(XmlDocument xDoc, string localName, string Value)
        {
            XmlNode xKey = xDoc.CreateNode(XmlNodeType.Element, "trust", localName, trustNS);
            xKey.InnerText = Value;

            return xKey.Clone();
        }

    }
}
